/*
#include <stdio.h>
#include <SDL.h>

static size_t buffer_len = 0;
static Uint8* audio_pos =NULL;
static Uint8* audio_buf = NULL;
#define BLOCK_SIZE 4096000

void read_audio_data(void* udata,Uint8* stream,int len)
{
    if(buffer_len == 0)
    {
        // 没有数据
        return;
    }

    SDL_memset(stream,0,len);

    len = (len < buffer_len) ? len : buffer_len;
    // 音量大小
    SDL_MixAudio(stream,audio_pos,len,SDL_MIX_MAXVOLUME);

    audio_pos += len;
    buffer_len -=len;
}

#undef main
int main()
{
    const char* path = "D:/videos/1.pcm";
    int ret = -1;
    FILE* audio_fd = NULL;
    SDL_AudioSpec spec;


    ret = SDL_Init(SDL_INIT_AUDIO | SDL_INIT_TIMER);

    if(ret != 0)
    {
        SDL_Log("failed to init!");
        return -1;
    }

    audio_fd = fopen(path,"r");
    if(!audio_fd)
    {
        SDL_Log("failed to open pcm file!");
        goto _FAIL;
    }

    audio_buf = (Uint8*)malloc(BLOCK_SIZE);
    if(!audio_buf){
        SDL_Log("failed to alloc memory");
        goto _FAIL;
    }

    spec.freq = 44100;
    spec.channels  = 2;
    spec.format = AUDIO_S16SYS;
    spec.silence = 0;
    spec.callback = read_audio_data;
    spec.userdata = NULL;

    ret = SDL_OpenAudio(&spec,NULL);
    if(ret != 0)
    {
        SDL_Log("failed to open audio device!");
        goto _FAIL;
    }

    // 0 : 播放状态
    SDL_PauseAudio(0);

    // 声卡通过回调向程序中读取数据
    do
    {
        buffer_len = fread(audio_buf,1,BLOCK_SIZE,audio_fd);
        audio_pos = audio_buf;

        while(audio_pos < (audio_buf + buffer_len)){
            SDL_Delay(1);
        }
    }while(buffer_len != 0);

    // 有可能缓冲区有数据没有播放完！
    SDL_CloseAudio();

_FAIL:
    if(audio_buf){
        free(audio_buf);
    }
    if(audio_fd)
    {
        fclose(audio_fd);
    }
    SDL_Quit();

    return 0;
}

#include <stdio.h>
#include <SDL.h>

#define BLOCK_SIZE 4096  // 减小块大小，避免延迟

static size_t buffer_len = 0;
static Uint8* audio_pos = NULL;
static Uint8* audio_buf = NULL;
static int audio_eof = 0;  // 标记文件是否读取完毕

void read_audio_data(void* udata, Uint8* stream, int len) {
    if (buffer_len == 0) {
        if (audio_eof) {
            SDL_PauseAudio(1);  // 数据播放完毕，暂停音频设备
            return;
        }
        // 可以在这里触发读取新数据（但需要线程安全）
        return;
    }

    SDL_memset(stream, 0, len);
    len = (len < buffer_len) ? len : buffer_len;
    SDL_MixAudio(stream, audio_pos, len, SDL_MIX_MAXVOLUME);

    audio_pos += len;
    buffer_len -= len;
}

#undef  main
int main() {
    const char* path = "D:/videos/1.pcm";
    FILE* audio_fd = NULL;
    SDL_AudioSpec spec;
    int ret;

    ret = SDL_Init(SDL_INIT_AUDIO | SDL_INIT_TIMER);
    if (ret != 0) {
        SDL_Log("Failed to init SDL: %s", SDL_GetError());
        return -1;
    }

    audio_fd = fopen(path, "rb");  // 以二进制模式打开
    if (!audio_fd) {
        SDL_Log("Failed to open PCM file!");
        goto _FAIL;
    }

    audio_buf = (Uint8*)malloc(BLOCK_SIZE);
    if (!audio_buf) {
        SDL_Log("Failed to allocate memory!");
        goto _FAIL;
    }

    spec.freq = 44100;
    spec.channels = 2;
    spec.format = AUDIO_S16SYS;  // 16-bit signed system byte order
    spec.silence = 0;
    spec.samples = 4096;         // 缓冲区大小
    spec.callback = read_audio_data;
    spec.userdata = NULL;

    ret = SDL_OpenAudio(&spec, NULL);
    if (ret != 0) {
        SDL_Log("Failed to open audio device: %s", SDL_GetError());
        goto _FAIL;
    }

    SDL_PauseAudio(0);  // 开始播放

    // 主循环：读取数据并填充缓冲区
    while (!audio_eof) {
        if (buffer_len == 0) {
            buffer_len = fread(audio_buf, 1, BLOCK_SIZE, audio_fd);
            audio_pos = audio_buf;

            if (buffer_len < BLOCK_SIZE) {
                audio_eof = 1;  // 文件读取完毕
            }
        }
        SDL_Delay(10);  // 避免CPU占用过高
    }

    // 等待音频播放完毕
    while (buffer_len > 0) {
        SDL_Delay(100);
    }

    SDL_CloseAudio();

_FAIL:
    if (audio_buf) free(audio_buf);
    if (audio_fd) fclose(audio_fd);
    SDL_Quit();
    return 0;
}

*/
#include <stdio.h>
#include <SDL.h>
#include <SDL_mutex.h>

#define BLOCK_SIZE 4096

static Uint8* audio_buf = NULL;
static size_t buffer_len = 0;
static Uint8* read_pos = NULL;
static Uint8* write_pos = NULL;
static int audio_eof = 0;
static SDL_mutex* audio_mutex = NULL;

void read_audio_data(void* udata, Uint8* stream, int len) {
    SDL_LockMutex(audio_mutex);

    if (buffer_len == 0 || audio_eof) {
        // 没有数据可播放，填充静音
        SDL_memset(stream, 0, len);
        SDL_UnlockMutex(audio_mutex);
        return;
    }

    // 计算实际可复制的数据量
    int copy_len = (len < buffer_len) ? len : buffer_len;

    SDL_memset(stream, 0, len);
    SDL_MixAudio(stream, read_pos, copy_len, SDL_MIX_MAXVOLUME);

    read_pos += copy_len;
    buffer_len -= copy_len;

    SDL_UnlockMutex(audio_mutex);
}

#undef main
int main() {
    const char* path = "D:/videos/1.pcm";
    FILE* audio_fd = NULL;
    SDL_AudioSpec spec;
    int ret;

    ret = SDL_Init(SDL_INIT_AUDIO);
    if (ret != 0) {
        SDL_Log("Failed to init SDL: %s", SDL_GetError());
        return -1;
    }

    // 创建互斥锁
    audio_mutex = SDL_CreateMutex();
    if (!audio_mutex) {
        SDL_Log("Failed to create mutex!");
        goto _FAIL;
    }

    audio_fd = fopen(path, "rb");
    if (!audio_fd) {
        SDL_Log("Failed to open PCM file!");
        goto _FAIL;
    }

    // 分配更大的缓冲区，确保数据供给充足
    audio_buf = (Uint8*)malloc(BLOCK_SIZE * 4);
    if (!audio_buf) {
        SDL_Log("Failed to allocate memory!");
        goto _FAIL;
    }

    read_pos = audio_buf;
    write_pos = audio_buf;

    spec.freq = 44100;
    spec.channels = 2;
    spec.format = AUDIO_S16SYS;
    spec.silence = 0;
    spec.samples = 1024;  // 较小的缓冲区减少延迟
    spec.callback = read_audio_data;
    spec.userdata = NULL;

    ret = SDL_OpenAudio(&spec, NULL);
    if (ret != 0) {
        SDL_Log("Failed to open audio device: %s", SDL_GetError());
        goto _FAIL;
    }

    SDL_PauseAudio(0);  // 开始播放

    // 改进的数据读取循环
    while (!audio_eof) {
        SDL_LockMutex(audio_mutex);

        // 计算缓冲区剩余空间
        size_t remaining_space = (audio_buf + BLOCK_SIZE * 4) - write_pos;

        // 如果读指针已经消费了数据，可以重置缓冲区
        if (buffer_len == 0 && read_pos != audio_buf) {
            read_pos = audio_buf;
            write_pos = audio_buf;
            remaining_space = BLOCK_SIZE * 4;
        }

        // 只有当缓冲区有足够空间时才读取新数据
        if (remaining_space >= BLOCK_SIZE && !audio_eof) {
            size_t read_bytes = fread(write_pos, 1, BLOCK_SIZE, audio_fd);

            if (read_bytes > 0) {
                write_pos += read_bytes;
                buffer_len += read_bytes;
            }

            if (read_bytes < BLOCK_SIZE) {
                audio_eof = 1;
                SDL_Log("File reading completed");
            }
        }

        SDL_UnlockMutex(audio_mutex);
        SDL_Delay(5);  // 更短的延迟，提高响应性
    }

    // 等待所有数据播放完毕
    while (1) {
        SDL_LockMutex(audio_mutex);
        int should_quit = (buffer_len == 0) || audio_eof;
        SDL_UnlockMutex(audio_mutex);

        if (should_quit) break;
        SDL_Delay(50);
    }

    SDL_Log("Playback finished");
    SDL_CloseAudio();

_FAIL:
    if (audio_mutex) SDL_DestroyMutex(audio_mutex);
    if (audio_buf) free(audio_buf);
    if (audio_fd) fclose(audio_fd);
    SDL_Quit();
    return 0;
}
